using System;
using System.IO;
using System.Reflection;
using System.Collections.Generic;

using OpenMetaverse;

using Nini;
using Nini.Config;
using log4net;

namespace Playtime.RegionModule
{
	public class Profile
	{
		/// <summary>
		/// Reference the logger instance
		/// </summary>
		private static readonly ILog mLog = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

		/// <summary>
		/// Globally unique identifier of this profile
		/// </summary>
		public UUID ID {get;set;}
		
		/// <summary>
		/// Userfriendly name of this profile
		/// </summary>
		public string Name {get; set;}
		
		/// <summary>
		/// The attributes associated with this profile
		/// </summary>
		public Dictionary<UUID, Attribute> Attributes { get; private set; }
		
		/// <summary>
		/// The Lua sourcecode managing this profile.
		/// </summary>
		public string ScriptCode { get; private set; }

		/// <summary>
		/// Is script code in this profile allowed to execute collect garbage
		/// </summary>
		private bool mLuaAllowCollectGarbage;
		public Profile()
		{
			Attributes = new Dictionary<UUID, Attribute>();
		}
		
		// load a named profile
		public Profile(IConfigSource configSource, bool luaAllowCollectGarbage) : this()
		{
			mLog.WarnFormat("[" + RegionModule.ModuleName + "]" + " loading profile");
			IConfig profileDescription = configSource.Configs["Profile"];
			Profile p = new Profile();
			p.ID = new UUID(profileDescription.Get("ID"));
			p.Name = profileDescription.Get("Name");
			foreach(string key in profileDescription.GetKeys())
			{
				if(key.ToLower().StartsWith("attribute."))
				{
					IConfig attributeDescription = configSource.Configs[profileDescription.Get(key)];
					if(attributeDescription != null)
					{
						Attribute a = new Attribute(attributeDescription);
						// do not attach the attribute if it has been previously defined
						if(!Attributes.ContainsKey(a.ID))
						{
							Attributes.Add(a.ID, a);
							a = Attributes[a.ID];
						}
					
				    	p.Attributes.Add(a.ID, a);
					}
					else
						mLog.WarnFormat("[" + RegionModule.ModuleName + "]" + " missing attribute description for: {0}", profileDescription.Get(key));
				}
			}
			
			if(profileDescription.Contains("Sourcecode"))
			{
				string codeFileName = profileDescription.Get("Sourcecode");
				ScriptCode = File.ReadAllText(Path.Combine("playtime", codeFileName));
			}
			mLuaAllowCollectGarbage = luaAllowCollectGarbage;
		}

		public ProfileInstance CreateInstance()
		{
			return new ProfileInstance(this, mLuaAllowCollectGarbage);
		}
	}
}

